ci(promote): make promotion idempotent and immutable-safe - #3
Merged
Conversation
The Promote learner branches workflow has never succeeded: it aborted the whole job whenever an immutable acc-<version>/start-of-module-N tag already existed. Those monthly tags are pre-seeded for the current month, so every run died on start-of-module-02 regardless of content, and the mutable start-of-module-N aliases never advanced. Rework the refspec assembly to be idempotent and immutability-safe: - Immutable version tag: create only if absent; if it already exists, leave it untouched (never overwrite) and skip it instead of failing. - Mutable alias: move it only when the freshly built tree differs from what the branch already points at, so unchanged public start-of-module-* branches are not gratuitously rewritten to new commit shas every promotion. - Treat "nothing changed" as success (skip the push) rather than an error. Verified locally against the current repo state: only start-of-module-06 and -07 (the QR-selector fix) are selected to move; 02-05 stay put and no tags are re-cut. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
There was a problem hiding this comment.
Pull request overview
This PR fixes the Promote learner branches GitHub Actions workflow so promotions are idempotent and safe around immutable archival tags (e.g., acc-YYYY-MM/start-of-module-N). It ensures existing immutable tags are never overwritten while allowing mutable start-of-module-* branches to advance only when the generated content actually changes.
Changes:
- Skip (do not fail) when an immutable
acc-<version>/start-of-module-*tag already exists, preserving immutability while allowing re-runs. - Only move mutable
start-of-module-*branches when the staged tree differs from the current remote branch tree. - Treat a “no changes” promotion as success and skip the push step.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/promote-branches.yml | Makes refspec assembly/push idempotent, avoids overwriting immutable tags, and skips no-op promotions. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
Address review: `git fetch ... || true` would hide a real failure (network/auth/remote down), leaving cur_tree empty for every branch and force-pushing ALL start-of-module-* branches -- exactly the gratuitous rewrite the tree comparison is meant to avoid. A wildcard refspec that matches nothing (e.g. the first-ever promotion, before any start branch exists) already exits 0, so no `|| true` is needed for the benign case. Drop it so genuine fetch failures abort the job under set -e. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3750cefd-d322-4f02-9184-c8ac3eba2fff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Promote learner branches workflow has never succeeded. It aborted the whole job whenever an immutable
acc-<version>/start-of-module-Ntag already existed, and those monthly tags are pre-seeded for the current month. So every run (including the initial commit and the PR #2 merge) died onstart-of-module-02regardless of content, and the mutablestart-of-module-Nlearner branches never advanced. The "refuse to overwrite an immutable tag" intent is correct; failing the entire job instead of skipping an already-present tag was the bug.Related Issue
N/A
Type of Change
Affected Services
web(Astro SSR + React)assets-svc(.NET 10)workforce-svc(Java 21 / Spring Boot 3)reporting-svc(Python FastAPI)notifications-svc(Python FastAPI)audit-svc(legacy Java 11 / Spring Boot 2.7)auth-svc(legacy Java 11 / Spring Boot 2.7)Changes Made
Reworked the refspec assembly in
promote-branches.ymlto be idempotent and immutability-safe:acc-<version>/start-of-module-N): created only if absent. If it already exists, it is left untouched (never overwritten) and skipped, instead of aborting the job.start-of-module-N): moved only when the freshly built tree differs from what the branch already points at, so unchanged public start branches are not gratuitously rewritten to new commit shas on every promotion.Testing
npm run test:e2e(Playwright) passesdotnet testinservices/assets-svcpassespytestinservices/reporting-svcand/orservices/notifications-svcpassesmvn testinservices/workforce-svcpassesmvn testinservices/audit-svcand/orservices/auth-svcpassesSimulated the exact refspec-assembly loop locally against the current repo state (built the staging refs with
build-branches.mjs, compared staged trees to the liveorigin/start-of-module-*trees and existing tags). Result: onlystart-of-module-06and-07(the QR-selector fix) are selected to move;02-05stay in place and no immutable tag is re-cut.Checklist
main(I have not hand-edited generated learner branches or promoted refs — see CONTRIBUTING.md)exercises.md) if neededAdditional Notes
Merging this only fixes the workflow logic; it does not itself run a promotion (this PR does not touch
course-build/**, so the push-triggered promotion won't fire). A promotion still needs to be dispatched to actually advancestart-of-module-06/07to the QR fix.Immutability note: by design this preserves existing
acc-2026-08/start-of-module-06and-07tags, which currently point at the pre-QR-fix content. After a promotion, the mutable start branches (what learners clone) carry the fix, while those two archival month tags stay frozen at the original snapshot. If the archival tags should also reflect the fix, that requires a deliberate re-cut under a new version — happy to do that as a follow-up.